package com.example.permissionsystem1_1.util.thirdPartyUtil;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

import java.security.SecureRandom;

/**
 * 实现发送阿里云短信验证码的功能的工具类
 * @author Administrator
 *
 */
public class SMSVerificationCodeUtil {
	/** 短信API产品名称（短信产品名固定，无需修改） */
	private static final String PRODUCT="Dysmsapi";
	/** 短信API产品域名（接口地址固定，无需修改） */
	private static final String DOMAIN="dysmsapi.aliyuncs.com";
	/** API产品所在地(地址固定,无需修改) */
	private static final String REGION="cn-hangzhou";
	
	/** 短信验证码的accesskeyId(每个系统只有一个就够了) */
	private static final String ACCESS_KEY_ID="LTAIVYZBvcLEl01P";
	/** 短信验证码的accesskeySecret(每个系统只有一个就够了) */
	private static final String ACCESS_KEY_SECRET="8B4zMH0UbVezXZxtqF4J9AItCh5RbR";
	/** 短信的统一签名(每个系统只有一个就够了) */
	private static final String SIGN_NAME="星牌马龙";
	/** 短信模板ID(每个系统只有一个就够了) */
	private static final String TEMPLATE_CODE="SMS_153840088";
	
	/**
	 * 生成指定位数(2-6位)短信验证码的工具方法
	 * @param num 指定生成的短信验证码的位数
	 * @return
	 */
	public static Integer createVerificationSMSCode(Integer num){
		//用于限制随机数随机生成值的上限的变量
		Integer randomNumber=1;
		if(num==null){//缺省情况下,按4位验证码处理
			num=4;
		}else if(num<2){//小于2时,按最短的2位验证码处理
			num=2;
		}else if(num>6){//大于6时,按最长的6位验证码处理
			num=6;
		}
		
		//根据指定的位数的不同,限制随机数随机生成值的上限也跟着改变
		for (int i = 0; i < num; i++) {
			randomNumber*=10;
		}
		randomNumber-=1;//得到的是:99、999、9999、99999、999999中的某一个值
		
		//创建线程安全的生成随机数的句柄工具类的对象
		SecureRandom secureRandom=new SecureRandom();
		//生成指定范围值的随机数
		Integer verificationSMSCode=secureRandom.nextInt(randomNumber);
		if(verificationSMSCode<(randomNumber+1)/10){//如果随机生成的随机数小于指定位数的最低值，则最高位补1从而让生成的随机数达到指定的位数
			verificationSMSCode+=(randomNumber+1)/10;
		}
		
		//返回生成的表示指定位数的短信验证码的随机数
		return verificationSMSCode;
	}
	
	/**
	 * 发送短信验证码的工具方法
	 * @param phoneNumbers 要发送短信验证码的手机号
	 * @param templateParam 短信验证码的回话模板
	 * @return 返回值为本次业务的id
	 * @throws ClientException
	 */
	public static String sendVerificationSMSCode(String phoneNumbers,String templateParam) throws ClientException{
		//设置短信超时时限
		System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
		System.setProperty("sun.net.client.defaultReadTimeout", "10000");
		//初始化IClientProfile,暂时不支持多地区(固定,无需修改)
		IClientProfile iClientProfile=DefaultProfile.getProfile(REGION,ACCESS_KEY_ID,ACCESS_KEY_SECRET);
		DefaultProfile.addEndpoint(REGION, REGION, PRODUCT,DOMAIN);
		IAcsClient iAcsClient=new DefaultAcsClient(iClientProfile);
		
		//构建阿里云短信验证码的请求对象
		SendSmsRequest smsRequest=new SendSmsRequest();
		//使用post方式来发送请求
		smsRequest.setMethod(MethodType.POST);
		//必填:短信签名-可在短信控制台中找到
		smsRequest.setSignName(SIGN_NAME);
		//必填:短信模板-可在短信控制台中找到，发送国际/港澳台消息时，请使用国际/港澳台短信模版
		smsRequest.setTemplateCode(TEMPLATE_CODE);
		//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
		//友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
		//smsRequest.setTemplateParam("{\"name\":\"Tom\", \"code\":\"123\"}");
		smsRequest.setTemplateParam(templateParam);
		//必填:待发送手机号。支持以逗号分隔的形式进行批量调用，批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式；发送国际/港澳台消息时，接收号码格式为国际区号+号码，如“85200000000”
		smsRequest.setPhoneNumbers(phoneNumbers);
		//可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段)
		//smsRequest.setSmsUpExtendCode("90997");
		//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
		//smsRequest.setOutId("yourOutId");
		
		//发送短信验证码的请求,并创建阿里云短信验证码的响应对象来接收短信验证码请求后的响应数据(请求失败这里会抛ClientException异常)
		SendSmsResponse smsResponse=iAcsClient.getAcsResponse(smsRequest);
		
		//获取短信验证码响应对象的响应码
		if(smsResponse.getCode()!=null){
			//如果短信验证码响应对象的响应码不为空,则进行进一步的判断
			if(smsResponse.getCode().equals("OK")){
				//如果响应码为"OK",则说明短信验证码请求成功
				System.err.println("短信验证码发送成功");
				//返回本次业务的id
				return smsResponse.getBizId();
			}else{
				//如果响应码不是"OK",则说明短信验证码请求失败
				String code=smsResponse.getCode();
				System.err.println("短信发送失败:"+code);
				return null;
			}
		}else{
			//如果短信验证码响应对象的响应码为空,则说明短信发送失败
			System.err.println("短信发送失败");
			return null;
		}
	}
	
	
	public static void main(String[] args) throws ClientException {
		Integer verificationSMSCode=SMSVerificationCodeUtil.createVerificationSMSCode(4);
		System.out.println(verificationSMSCode);
		
		String templateParam ="{\"code\":\""+verificationSMSCode+"\"}";
		String phoneNumbers="12345678";
		String bizId=SMSVerificationCodeUtil.sendVerificationSMSCode(phoneNumbers, templateParam);
		System.out.println(bizId);
	}
	
}
